
#include "SDL.h"

#define GL_API_CALL
#define GL_VERTEX_SHADER 0x8B31
#define GL_FRAGMENT_SHADER 0x8B30

typedef unsigned int GLenum;
typedef int GLint;
typedef int GLsizei;
typedef unsigned int GLuint;
typedef float GLfloat;
typedef char GLchar;

typedef GLuint (GL_API_CALL *glCreateShader_fn) (GLenum type);
typedef void (GL_API_CALL *glShaderSource_fn) (GLuint shader, GLsizei count, const GLchar **string, const GLint *length);
typedef void (GL_API_CALL *glCompileShader_fn) (GLuint shader);
typedef GLuint (GL_API_CALL *glCreateProgram_fn) (void);
typedef void (GL_API_CALL *glUseProgram_fn) (GLuint program);
typedef void (GL_API_CALL *glLinkProgram_fn) (GLuint program);
typedef void (GL_API_CALL *glAttachShader_fn) (GLuint program, GLuint shader);
typedef GLint (GL_API_CALL *glGetUniformLocation_fn) (GLuint program, const GLchar *name);
typedef void (GL_API_CALL *glUniform1f_fn) (GLint location, GLfloat v0);
typedef void (GL_API_CALL *glRecti_fn)(GLint x1, GLint y1, GLint x2, GLint y2);
#if defined(GLSL_LOG)
typedef void (GL_API_CALL *glGetProgramInfoLog_fn) (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
#endif

const char *g_src_vs =
    "#version 150 compatibility\n"
    "void main(){"
        "gl_Position=gl_Vertex;"
    "}";
const char *g_src_fs =
    "#version 150 compatibility\n"
    "uniform float t;"
    "void main(){"
        "gl_FragColor=vec4(1.);"
    "}";

int main(void) {
    glCreateShader_fn glCreateShader;
    glShaderSource_fn glShaderSource;
    glCompileShader_fn glCompileShader;
    glCreateProgram_fn glCreateProgram;
    glUseProgram_fn glUseProgram;
    glLinkProgram_fn glLinkProgram;
    glAttachShader_fn glAttachShader;
    glGetUniformLocation_fn glGetUniformLocation;
    glUniform1f_fn glUniform1f;
    glRecti_fn glRecti;
#if defined(GLSL_LOG)
    glGetProgramInfoLog_fn glGetProgramInfoLog;
#endif

    SDL_WindowID win;
    SDL_Event evt;
    GLuint sh, prog;
#if defined(GLSL_LOG)
    GLchar log[2048];
#endif

    SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO);
    win = SDL_CreateWindow(NULL, 0, 0, 600, 600, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL | SDL_WINDOW_BORDERLESS);
    SDL_GL_CreateContext(win);

    glCreateShader = (glCreateShader_fn) SDL_GL_GetProcAddress("glCreateShader");
    glShaderSource = (glShaderSource_fn) SDL_GL_GetProcAddress("glShaderSource");
    glCompileShader = (glCompileShader_fn) SDL_GL_GetProcAddress("glCompileShader");
    glCreateProgram = (glCreateProgram_fn) SDL_GL_GetProcAddress("glCreateProgram");
    glUseProgram = (glUseProgram_fn) SDL_GL_GetProcAddress("glUseProgram");
    glLinkProgram = (glLinkProgram_fn) SDL_GL_GetProcAddress("glLinkProgram");
    glAttachShader = (glAttachShader_fn) SDL_GL_GetProcAddress("glAttachShader");
    glGetUniformLocation = (glGetUniformLocation_fn) SDL_GL_GetProcAddress("glGetUniformLocation");
    glUniform1f = (glUniform1f_fn) SDL_GL_GetProcAddress("glUniform1f");
    glRecti = (glRecti_fn) SDL_GL_GetProcAddress("glRecti");
#if defined(GLSL_LOG)
    glGetProgramInfoLog = (glGetProgramInfoLog_fn) SDL_GL_GetProcAddress("glGetProgramInfoLog");
#endif

    prog = glCreateProgram();

    sh = glCreateShader(GL_VERTEX_SHADER);
    glAttachShader(prog, sh);
    glShaderSource(sh, 1, &g_src_vs, NULL);
    glCompileShader(sh);
    sh = glCreateShader(GL_FRAGMENT_SHADER);
    glAttachShader(prog, sh);
    glShaderSource(sh, 1, &g_src_fs, NULL);
    glCompileShader(sh);

    glLinkProgram(prog);
#if defined(GLSL_LOG)
    glGetProgramInfoLog(prog, sizeof(log), NULL, log);
    printf("GLSL info log:\n%s\n", log);
#endif
    glUseProgram(prog);

    while (1) {
        SDL_PollEvent(&evt);
        if (evt.type == SDL_KEYDOWN) break;
        glUniform1f(glGetUniformLocation(prog, "t"), SDL_GetTicks() * 0.001f);
        glRecti(-1,-1,1,1);
        SDL_GL_SwapWindow(win);
    }

    SDL_Quit();
    return 0;
}
